#include <string.h>
#include "main.h"
#include "gd32f30x.h"
#include "update.h"
#include "usart.h"
#include "type.h"
#include "flash.h"
#include "update.h"
#include "message.h"
#include "core_cm4.h"
#include "settings.h"
#ifdef ENABLE_I2C_TEST
#include "i2c.h"
#endif

/*串口升级协议如下：
    cmd + data_lenght + data0 + ....+ datax + checksum 
    1、获取版本号             0x01 0x02 0x00 0x00 checksum
    2、升级
        1、进入升级模式        0x02 0x02 0x00 0x00 checksum
        2、升级文件大小        0x03 0x04 0x00 0x00 0x00 0x00 checksum
        3、数据包发送          0x04 0x10 0x00 0x00 0x00 0x00 .....  checksum
        4、数据包发送完成       0x05 0x02 0x00 0x00 checksum
    3、开锁
        0x06 0x02 0x00 0x00 checksum
    4、关门
        0x07 0x02 0x00 0x00 checksum        
*/

#define APPCATION_VERSION_DATE __DATE__
#define APPCATION_VERSION_TIME __TIME__

#define I2C_UPGRADE_DATA_PACKAGES_LENGHT   0x40
#define UART_UPGRADE_DATA_PACKAGES_LENGHT  0x10

static MI_CHAR version[36] = {0};
static MI_U32 upgrade_file_size = 0;
static MI_U32 w_time = 0;
static MI_U16 packets_numer = 0;
static MI_U16 remain_packets_numer = 0;
static MI_U8 w_buff[UART_UPGRADE_DATA_PACKAGES_LENGHT] = {0};
static MI_U8 i2c_w_buff[I2C_UPGRADE_DATA_PACKAGES_LENGHT] = {0};

static void app_soft_reset(void)
{
    __ASM volatile ("cpsid i");
    NVIC_SystemReset();
}

static MI_U16 CRC16(MI_U8 * buf, MI_U16 len)
{
	MI_U16 i;
	MI_U16 crc = 0xffff;
 
	if (len == 0) {
		len = 1;
	}
	while (len--) {
        
		crc ^= *buf;
		for (i = 0; i<8; i++) 
		{            
			if (crc & 1) {               
				crc >>= 1;        
				crc ^= 0xA001;            
			}      
			else {               
				crc >>= 1;            
			}       
		}     
		buf++;
	}
	return(crc);
}

static MI_BOOL calculate_checksum_and_length(MI_U8 * buf, MI_U16 len)
{
    MI_U16 crc16 = CRC16(buf,len-2);
    if ((crc16 & 0x00ff) == buf[len-2] && ((crc16 >> 8) & 0x00ff) == buf[len-1])
    {
        if (buf[UART_CMD_LENGTH] == (len-2-2))
        {
            return MI_TRUE;
        }
        else
        {
            printf("crc16 right ,but cmd error\r\n"); 
            return MI_FALSE; 
        }
    }
    else
    {
        printf("crc16 error and right crc16 = 0x%04x\r\n",crc16);  
        return MI_FALSE; 
    }
}

void handle_usart2_message(uint8_t *p_buf,int len)
{    
    switch (p_buf[UART_CMD_INDEX])
    {
        case UART_OPEN_LOCK_CMD:

            if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
            {
                printf("Now to open lock\r\n");
                usart1_send_string(p_buf,len);
            }
            break;
        case UART_CLOSE_LOCK_CMD:
            
            if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
            {
                printf("Now to close lock\r\n");
                usart1_send_string(p_buf,len);
            }
            break;
        case UART_GET_SYSTEM_VERSION_CMD:

            if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
            {
                char version[28] = {0};

                sprintf(version,"%s %s",APPCATION_VERSION_DATE,APPCATION_VERSION_TIME);
                usart1_send_string(version,20);
            }
            break;
        case UART_ENTER_SYSTEM_UPDATE_MODE_CMD:
        /* 进入升级模式命令 指示灯变为100ms闪烁一次*/
        if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
        {
            led_freq = 100;
            w_time = 0;
            packets_numer = 0;
            upgrade_file_size = 0;
            remain_packets_numer = 0;
            isRunningUpdate = 1;
            printf("Mcu Receive Update Command and Wait Receive Data Packets \r\n");
            printf("Now to Erase Download Pages \r\n");
            gd32_flash_erase(DOWNLOAD_START_ADDRESS,DOWNLOAD_END_ADDRESS);
        }
        break; 
    case UART_GET_SYSTEM_FILE_SIZE_CMD:

        printf("Erase Download Pages \r\n");
        if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
        {
            int a = (int)p_buf[2];
            int b = (int)p_buf[3];
            int c = (int)p_buf[4];
            int d = (int)p_buf[5];
            upgrade_file_size = (a<<24) | (b<<16) | (c<<8) | (d);

            if (upgrade_file_size % UART_UPGRADE_DATA_PACKAGES_LENGHT == 0)  //如果整除16
            {
                packets_numer = upgrade_file_size/UART_UPGRADE_DATA_PACKAGES_LENGHT;
            }
            else
            {
                packets_numer = ((upgrade_file_size/UART_UPGRADE_DATA_PACKAGES_LENGHT) + 1);
            }
            printf("End Erase Download Pages Down\r\n");
            printf("\r\n");

            printf("receive upgrade file size %d\r\n",upgrade_file_size);
            printf("data packets number  %d\r\n",packets_numer);
            printf("\r\n");
            //Usart_SendString(USART2,(char *)p_buff,len);
        }
        break;  

        case UART_RECEIVE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
        {
            printf("receive packets........................%d [100] \r\n",(((w_time + 1) * 100) / packets_numer));
            memset(w_buff,0,sizeof(w_buff));
            memcpy(w_buff,&p_buf[2],sizeof(w_buff));

            int ret = gd32_flash_write(DOWNLOAD_START_ADDRESS+(w_time * UART_UPGRADE_DATA_PACKAGES_LENGHT),
                                                                w_buff,sizeof(w_buff));
            if (w_time + 1 == packets_numer)
            {
                led_freq = 500;
                printf("receive packets........................ done!\r\n");
            }
            w_time ++;
            //Usart_SendString(USART2,(char *)p_buf,20);
        }
        break;  
    case UART_COMPLETE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buf,len) == MI_TRUE)
        {
            int flag;
            system_info_set_update_flag(1);
            printf("Now Reboot %d \r\n");
            app_soft_reset();
        }
        break;           
        default:break;
    }          
}

#ifdef ENABLE_I2C_TEST

#if I2C1_MODE == I2C1_MODE_SLAVE
MI_BOOL send_i2c_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[UART_CMD_INDEX])
    {
    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            char version[28] = {0};
            sprintf(version,"%s %s",APPCATION_VERSION_DATE,APPCATION_VERSION_TIME);
            memset(i2c_txbuffer,0,128);
            memcpy(i2c_txbuffer,version,strlen(version));
            printf("get version = %s\r\n",version);
        }
        break;
    default:
        break;
    }    
    return MI_TRUE;
}

MI_BOOL handle_i2c_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[I2C_CMD_INDEX])
    {
    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        /* Noting to do send_i2c_message 中处理*/
        break;
    case I2C_ENTER_SYSTEM_UPDATE_MODE_CMD:
        /* 进入升级模式命令 指示灯变为100ms闪烁一次*/
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            led_freq = 100;
            w_time = 0;
            packets_numer = 0;
            upgrade_file_size = 0;
            remain_packets_numer = 0;
            isRunningUpdate = 1;
            printf("Mcu Receive Update Command and Wait Receive Data Packets \r\n");
            printf("Now to Erase Download Pages \r\n");
            printf("\r\n");
            gd32_flash_erase(DOWNLOAD_START_ADDRESS,DOWNLOAD_END_ADDRESS);
            printf("\r\n");
        }
        break;
    case I2C_GET_SYSTEM_FILE_SIZE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            int a = (int)p_buff[2];
            int b = (int)p_buff[3];
            int c = (int)p_buff[4];
            int d = (int)p_buff[5];
            upgrade_file_size = (a<<24) | (b<<16) | (c<<8) | (d);

            if (upgrade_file_size % I2C_UPGRADE_DATA_PACKAGES_LENGHT == 0)  //如果整除128 
            {
                packets_numer = upgrade_file_size/I2C_UPGRADE_DATA_PACKAGES_LENGHT;
            }
            else
            {
                packets_numer = ((upgrade_file_size/I2C_UPGRADE_DATA_PACKAGES_LENGHT) + 1);
            }
            printf("End Erase Download Pages DONE!!\r\n");
            printf("\r\n");
            printf("receive upgrade file size %d\r\n",upgrade_file_size);
            printf("data packets number  %d\r\n",packets_numer);
            printf("\r\n");
        }
        break; 
    case I2C_RECEIVE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            printf("receive packets........................%03d [100] \r\n",(((w_time + 1) * 100) / packets_numer));
            memset(i2c_w_buff,0,sizeof(i2c_w_buff));
            memcpy(i2c_w_buff,&p_buff[2],sizeof(i2c_w_buff));

            gd32_flash_write(DOWNLOAD_START_ADDRESS+(w_time * I2C_UPGRADE_DATA_PACKAGES_LENGHT),i2c_w_buff,sizeof(i2c_w_buff));

            if (w_time + 1 == packets_numer)
            {
                led_freq = 500;
                printf("receive packets........................ done!\r\n");
            }
            w_time ++;
        }
        break;
    case I2C_COMPLETE_SYSTEM_UPDATE_CMD:
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            system_info_set_update_flag(1);
            printf("Now Reboot !\r\n");
            app_soft_reset();
        }
        break;   

    default:break;
    }

#if DEBUG
    if(p_buff != 0)
    {
        for(int i=0;i<len;i++)
        {
            printf("0x%02x " ,p_buff[i]);
        }
        printf("\r\n");
    }
#endif    
    return MI_TRUE;
}
#endif
#endif

void handle_spi1_message(uint8_t *p_buf,int len)
{
    print_register_value(p_buf,len);

}